#include "uart.h"
#include "stdio.h"

//定义UART1串口初始化函数
void UART_Init(void) {
	//用于配置串口1的GPIO引脚工作参数
	GPIO_InitTypeDef GPIO_Config;
	
	//用于配置UART1控制器工作参数
	USART_InitTypeDef UART_Config;
	
	//打开时钟GPIOA和UART1控制器的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
	//配置串口1的TX发送数据引脚工作模式
	GPIO_Config.GPIO_Pin = GPIO_Pin_9;					//UART1的TX->PA9
	GPIO_Config.GPIO_Mode = GPIO_Mode_AF_PP;		//配置为复用推挽输出
	GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz;  //最大输出速度
	GPIO_Init(GPIOA, &GPIO_Config);
	
	//配置串口1的RX接收数据引脚工作模式
	GPIO_Config.GPIO_Pin = GPIO_Pin_10;					//UART1的RX->PA10
	GPIO_Config.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输入浮空
	GPIO_Init(GPIOA, &GPIO_Config);
	
	//配置UART1控制器的工作参数
	UART_Config.USART_BaudRate = BOUND;						 //指定波特率为115200
	UART_Config.USART_WordLength = USART_WordLength_8b;	//指定数据位为8位
	UART_Config.USART_StopBits = USART_StopBits_1;	//指定停止位为1位
	UART_Config.USART_Parity = USART_Parity_No;		//不校验
	UART_Config.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不采用硬件控制数据流操作
	UART_Config.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //使能发送和接收功能
	USART_Init(USART1, &UART_Config);
	
	//打开UART1控制器开始传输数据了
	USART_Cmd(USART1, ENABLE);
	
	//对于NVIC控制器的配置 
	NVIC_InitTypeDef NVIC_Config;
	NVIC_Config.NVIC_IRQChannel = USART1_IRQn;//指定串口1的中断通道 
	NVIC_Config.NVIC_IRQChannelPreemptionPriority = 2;//抢占式优先级为2
	NVIC_Config.NVIC_IRQChannelSubPriority = 3;//指定响应式优先级为3 
	NVIC_Config.NVIC_IRQChannelCmd = ENABLE; //打开串口1的中断通道 
	NVIC_Init(&NVIC_Config);
	
	//开启串口1的接收中断功能
	//当UART1控制器接收到数据后会给CPU核发送一个中断信号
	//通过CPU核数据准备就绪, 让其读取数据 
	//CPU核读取结束,再回到被打断的位置继续执行 
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
}

//定义发送字符函数
void UART_Putc(u8 c) {
	//首先要判断发送数据寄存器中是否还有数据了,如果还有数据则轮询死等，否则可以继续发送数据
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
	
	//发送字符
	USART_SendData(USART1, c);
}

//定义发送字符串函数
//pstr = "hello,world\n"
void UART_Puts(u8 *pstr) {
	while(*pstr) {
		UART_Putc(*pstr);
		pstr++;
	}
}

//定义接收字符函数
u8 UART_Getc(void) {
	//采用轮询方式判断接收缓冲区是否有数据，如果没有数据轮询死等，否则读取数据并且返回
	while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
	//直接返回从上位机获取的字符数据
	return (u8)USART_ReceiveData(USART1);
}

//定义接收字符串函数
void UART_Gets(u8 buf[], u32 len) {
	int i;
	for(i = 0; i < len - 1; i++) {
		buf[i] = UART_Getc();
		if(buf[i] == '\n')
			break;
	}
	buf[i - 1] = '\0'; //上位机的串口工具SSCOM发送来的字符串格式是："hello\r\n"
}

//重定向printf,将来printf打印输出的信息通过UART1发送给上位机 
int fputc(int c, FILE* fp){
	//首先判断发送寄存器中是否还有数据,还有数据轮询死等,否则可以继续发送数据
	while((USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET));
	//发送字符
	USART_SendData(USART1, (u8)c);
}





